<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <title>我的书籍</title>
    <link rel="stylesheet" href="./lib/element-plus.css">
    <script src="./lib/vue.global.js"></script>
    <script src="./lib/element-plus.js"></script>
    <style>
        body {
            margin: 0;
            padding: 0;
            font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Microsoft YaHei', sans-serif;
            overflow: hidden;
        }

        .app-container {
            display: flex;
            flex-direction: column;
            height: 100vh;
            overflow: hidden;
        }

        .header {
            background-color: #409EFF;
            color: white;
            padding: 0 20px;
            height: 60px;
            display: flex;
            align-items: center;
        }

        .main-content {
            display: flex;
            flex: 1;
            overflow: hidden;
            font-size: 16px;
            overflow: hidden;
        }

        .left-sidebar {
            width: 180px;
            background-color: #545c64;
            color: white;
            overflow-y: hidden;
        }

        .content-area {
            flex: 1;
            padding: 20px;
            overflow: hidden;
        }

        .right-sidebar {
            width: 520px;
            background-color: #f5f7fa;
            overflow: hidden;
        }

        .footer {
            height: 40px;
            background-color: #e9eef3;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 12px;
            color: #666;
        }

        .input-with-select .el-input-group__prepend {
            background-color: var(--el-fill-color-blank);
        }
    </style>
</head>

<body>
    <div id="app">
        <div class="app-container">
            <!-- 顶部导航栏 -->
            <el-header class="header">
                <div style="display: flex; align-items: center;">
                    <div style="font-size: 20px; font-weight: bold;">AI小说创作平台</div>
                    <el-select v-model="currentModel" placeholder="选择AI模型" style="margin-left: 20px; width: 200px;">
                        <el-option v-for="model in aiModels" :key="model.value" :label="model.label" :value="model.value"></el-option>
                    </el-select>
                    <el-input-number v-model="questionWordLimit" :min="100" :max="20000" placeholder="提问字数" style="margin-left: 20px; width: 150px;"></el-input-number>
                    <el-menu mode="horizontal" background-color="#409EFF" text-color="#fff" active-text-color="#ffd04b"
                        style="margin-left: 20px;">
                        <el-menu-item>我的作品</el-menu-item>
                    </el-menu>
                    <el-button type="primary" @click="previewDialogVisible = true" style="margin-left: 20px;">
                        预览问题
                    </el-button>

                </div>
                <!-- <el-row >
                        <el-button link type="button.type"  @click="showBookDialog" style="width: 45%; margin-bottom: 10px;">
                            编辑书籍
                        </el-button>
                    </el-row> -->

            </el-header>

            <!-- 主体内容区 -->
            <div class="main-content">
                <!-- 左侧导航 -->
                <el-aside class="left-sidebar">
                    <el-menu default-active="1" background-color="#545c64" text-color="#fff"
                        active-text-color="#ffd04b">

                        <!-- 章节操作按钮 -->
                        <el-row style="padding: 10px; border-top: 1px solid #666;">
                            <el-button type="primary" size="small" @click="showCreateChapterDialog"
                                style="width: 45%; margin-bottom: 10px;">
                                创建
                            </el-button>
                            <el-button type="danger" size="small" @click="deleteSelectedChapter" style="width: 45%;"
                                :disabled="!selectedChapter">
                                删除
                            </el-button>
                        </el-row>
                        <!-- 章节列表 -->
                        <div v-if="chapters.length > 0" style="height: 78vh;">
                            <el-menu-item style="height: 30px;" v-for="chapter in chapters" :key="chapter.id"
                                :index="'chapter-'+chapter.id" @click="selectChapter(chapter)"
                                :class="{'is-active': selectedChapter && selectedChapter.id === chapter.id}">
                                第{{chapter.index}}章:{{ chapter.name }}
                            </el-menu-item>
                        </div>
                        <el-pagination v-if="chapters.length > 0" layout="prev, pager, next" :total="totalChapters"
                            :page-size="pageSize" v-model:current-page="currentPage" @current-change="handlePageChange"
                            style="padding: 10px;">
                        </el-pagination>
                    </el-menu>
                </el-aside>
                <el-main class="content-area">
                    <div v-if="!selectedChapter">
                        <p>请选择一个章节进行编辑。</p>
                    </div>
                    <!-- 顶部工具栏 -->
                    <div v-else>
                        <div class="toolbar">
                            <el-row justify="start" align="middle" style="margin-bottom: 10px;">
                                <el-col :span="12">
                                    <h3 style="margin-right: 10px;">{{selectedChapter.name||暂无}}</h3>
                                </el-col>
                                <el-col :span="6" :push="6">
                                    <el-button-group>
                                        <el-button type="primary" @click="save">保存</el-button>
                                        <el-button type="primary" @click="articleContent=''">清除</el-button>
                                        <el-button type="primary" @click="articleContent=oldText">撒消</el-button>
                                        <el-button type="primary" @click="showSummaryDialog">章纲</el-button>
                                    </el-button-group>
                                </el-col>
                            </el-row>
                        </div>
                        <!-- 文字输入区域 -->
                        <el-input ref="articleInput" @input="scrollToBottom" type="textarea" :rows="23"
                            placeholder="请输入您的文章内容..." v-model="articleContent" style="margin-bottom: 20px;"
                            ref="articleInput">
                        </el-input>

                        <el-input type="textarea" :rows="7" placeholder="向AI提问..." v-model="aiQuestion"
                            style="margin-bottom: 10px;" @keydown.ctrl.enter="submitAIQuestion"></el-input>
                        <el-row justify="end">
                            <el-button type="danger" @click="stopAI" :disabled="!aiLoading">
                                停止
                            </el-button>
                            <el-button type="primary" @click="submitAIQuestion" :loading="aiLoading">
                                提问
                            </el-button>
                        </el-row>
                    </div>
                </el-main>

                <el-aside class="right-sidebar">
                    <el-tabs type="border-card">
                        <el-tab-pane label="提示词">
                            <div style="padding: 10px;">
                                <el-input v-model="book.prompt" type="textarea" :rows="33" placeholder="输入AI提示词..."
                                    style="margin-bottom: 10px;">
                                </el-input>
                                <el-button type="primary" style="width: 100%;" @click="updateBook">
                                    保存提示词
                                </el-button>

                            </div>
                        </el-tab-pane>
                        <el-tab-pane label="设定">
                            <div style="padding: 10px;">
                                <el-input v-model="book.settings" type="textarea" :rows="33" placeholder="输入小说设定..."
                                    style="margin-bottom: 10px;">
                                </el-input>
                                <el-button type="primary" style="width: 100%;" @click="updateBook">
                                    保存设定
                                </el-button>
                            </div>
                        </el-tab-pane>
                        <el-tab-pane label="元素管理">
                            <div style="padding: 10px;">
                                <el-table :data="elements" style="width: 100%" height="660"
                                    @selection-change="handleElementSelectionChange" @row-dblclick="editElement">
                                    <el-table-column type="selection" width="55"></el-table-column>
                                    <el-table-column prop="name" label="名称" width="120"></el-table-column>
                                    <el-table-column prop="type" label="类型" width="100"></el-table-column>
                                    <el-table-column prop="status" label="状态" width="80">
                                        <template #default="scope">
                                            <el-button size="small" :type="scope.row.status === 1 ? 'success' : 'info'"
                                                @click="toggleElementStatus(scope.row)">
                                                {{ scope.row.status === 1 ? '出场' : '离场' }}
                                            </el-button>
                                        </template>
                                    </el-table-column>
                                    <!-- <el-table-column prop="content" label="描述"></el-table-column> -->

                                </el-table>
                                <el-pagination small layout="prev, pager, next" :total="elementTotal"
                                    v-model:current-page="elementPage" v-model:page-size="elementPageSize"
                                    @current-change="fetchElements" style="margin-top: 10px;">
                                </el-pagination>
                                <div style="margin-top: 10px;">
                                    <el-button type="primary" @click="showAddElementDialog">添加元素</el-button>
                                    <el-button type="danger" @click="deleteSelectedElements"
                                        :disabled="selectedElements.length === 0">
                                        删除选中
                                    </el-button>
                                    <el-button type="warning" @click="batchChangeStatus"
                                        :disabled="selectedElements.length === 0">
                                        批量{{ selectedElements.some(e => e.status === 0) ? '出场' : '离场' }}
                                    </el-button>
                                </div>
                            </div>
                        </el-tab-pane>
                    </el-tabs>

                </el-aside>

            </div>

            <!-- 底部状态栏 -->
            <el-footer class="footer">

                <span> 字数: {{ articleContent.length }}</span>
            </el-footer>
        </div>
        <!-- 在el-footer之前添加 -->
        <el-dialog v-model="createChapterDialogVisible" title="创建新章节">
            <el-form>
                <el-form-item label="章节序号" required>
                    <el-input-number v-model="newChapterIndex" :min="1" :max="10000"
                        placeholder="请输入章节序号"></el-input-number>
                </el-form-item>
                <el-form-item label="章节名称" required>
                    <el-input v-model="newChapterName" placeholder="请输入章节名称"></el-input>
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="createChapterDialogVisible = false">取消</el-button>
                <el-button type="primary" @click="createChapter">确认</el-button>
            </template>
        </el-dialog>
        <el-dialog v-model="summaryDialogVisible" title="编辑章纲" width="60%">
            <el-input v-model="summary" type="textarea" :rows="20" placeholder="请输入章纲内容..." style="width: 100%;">
            </el-input>
            <template #footer>
                <el-button @click="summaryDialogVisible = false">取消</el-button>
                <el-button type="primary" @click="save">保存</el-button>
                <el-button type="primary" @click="createAiSummary">生成</el-button>
            </template>
        </el-dialog>
        <!-- 元素编辑对话框 -->
        <el-dialog v-model="elementDialogVisible" :title="currentElement._id ? '编辑元素' : '添加元素'">
            <el-form :model="currentElement" label-width="80px">
                <el-form-item label="名称" required>
                    <el-input v-model="currentElement.name"></el-input>
                </el-form-item>
                <el-form-item label="类型" required>
                    <el-input v-model="currentElement.type" placeholder="请输入或选择类型" class="input-with-select">
                        <template #append>
                            <el-select v-model="currentElement.type" placeholder="选择类型" style="width: 120px">
                                <el-option v-for="item in elementTypes" :key="item.value" :label="item.label"
                                    :value="item.value">
                                </el-option>
                            </el-select>
                        </template>
                    </el-input>
                </el-form-item>
                <el-form-item label="状态">
                    <el-radio-group v-model="currentElement.status">
                        <el-radio :label="1">出场</el-radio>
                        <el-radio :label="0">离场</el-radio>
                    </el-radio-group>
                </el-form-item>
                <el-form-item label="描述">
                    <el-input v-model="currentElement.content" type="textarea" :rows="5" placeholder="请输入元素描述">
                    </el-input>
                </el-form-item>
            </el-form>
            <template #footer>
                <el-button @click="elementDialogVisible = false">取消</el-button>
                <el-button type="primary" @click="saveElement">保存</el-button>
            </template>
        </el-dialog>
        <el-dialog v-model="previewDialogVisible" title="问题预览" width="50%">
            <el-input type="textarea" :rows="30" v-model="previewContent">
            </el-input>
            <el-button style="margin-top: 20px;" type="primary" @click="generatePreviewQuestion">生成问题</el-button>
        </el-dialog>
    </div>

    <script type="module">
        import { http } from './api.js';
        import ai from './ai.js';

        const { createApp } = Vue;

        createApp({
            data() {
                return {
                    previewDialogVisible: false,
                    previewContent: '',
                    currentModel: 'gemma3:27b-it-qat',
                    aiModels: [
                        { value: 'gemma3:27b-it-qat', label: 'g3:27b-量化' },
                        { value: 'gemma3:12b-it-qat', label: 'g3:12b-量化' },
                        { value: 'gemma3:4b-it-qat', label: 'g3:4b-量化' },
                        { value: 'gemma3:1b-it-qat', label: 'g3:1b-量化' },
                      
                    ],
                    elements: [],
                    elementPage: 1,
                    elementPageSize: 10,
                    elementTotal: 0,
                    selectedElements: [],
                    elementDialogVisible: false,
                    currentElement: {
                        name: '',
                        type: '',
                        status: 1,
                        content: ''
                    },
                    elementTypes: [
                        { value: '主角', label: '主角' },
                        { value: '男配', label: '男配' },
                        { value: '女主', label: '女主' },
                        { value: '反派', label: '反派' },
                        { value: '宠物', label: '宠物' },
                        { value: '法宝', label: '法宝' },
                        { value: '灵药', label: '灵药' },
                        { value: '武器', label: '武器' },
                        { value: '技能', label: '技能' }
                    ],
                    summaryDialogVisible: false,
                    aiPrompt: '',
                    fontSize: 16,
                    theme: 'light',
                    bookId: null,
                    chapters: [],
                    selectedChapter: null,
                    currentPage: 1,
                    pageSize: 24,
                    totalChapters: 0,
                    createChapterDialogVisible: false,
                    newChapterName: '',
                    articleContent: '',
                    aiQuestion: '',
                    aiLoading: false,
                    showAIChat: true,
                    newChapterIndex: 1,
                    summary: '',
                    oldText: '',
                    book: "",
                    stopAIRequest: false,
                    questionWordLimit: 2000,
                }
            },
            computed: {
                wordCount() {
                    // 中文、韩文、日文等按2个字符计算
                    let count = 0;
                    for (let char of this.articleContent) {
                        count += /[\u4e00-\u9fa5\u3130-\u318F\uAC00-\uD7AF\u3040-\u30FF]/.test(char) ? 2 : 1;
                    }
                    return count;
                }
            },
            created() {
                const urlParams = new URLSearchParams(window.location.search);
                const bookId = urlParams.get('bookId');
                if (bookId) {
                    this.bookId = bookId;
                    this.fetchBook();
                    this.fetchChapters();
                    this.fetchElements();
                    this.aiQuestion=localStorage.getItem('lastQuestion')||"";
                }
            },
            methods: {
                async submitAIQuestion() {
                    await this.generatePreviewQuestion()
                    // 保存提问内容到localStorage
                    localStorage.setItem('lastQuestion', this.aiQuestion);
                    this.aiLoading = true;
                    this.stopAIRequest = false;  // 重置停止标志
                    this.oldText = this.articleContent;
                    try {
                        // 修改AI请求方法以支持停止
                        const response = await ai.streamOllamaRequest(this.previewContent, this.book.prompt, (msg,stop) => {
                            if (this.stopAIRequest){
                                stop();
                                return;  
                            } // 如果点击停止则不再处理消息
                            this.articleContent += msg;
                            this.articleContent = ai.formatText(this.articleContent);
                            this.scrollToBottom();
                        },this.currentModel,this.questionWordLimit);
                    } catch (error) {
                        if (!this.stopAIRequest) {  // 如果不是主动停止导致的错误才显示错误
                            this.$message.error('提问失败');
                            console.error(error);
                        }
                    } finally {
                        this.aiLoading = false;
                    }
                },
                async createAiSummary() {
                    let prompt = "你是一个小说编辑。"
                    let text = "小说的章节内容如下：\n" + this.articleContent + "\n"
                    text += "请根据小说的内容生成章节介绍。"
                    ai.streamOllamaRequest(text, prompt, (response) => {
                        this.summary += response;
                    })

                },
                async generatePreviewQuestion() {                   // 这里添加生成问题的逻辑
                    //this.previewContent = "这是生成的问题预览内容";
                    let text = "【小说设定】\n" + this.book.settings + "\n"
                    let res = await http.searchEle({ bookId: this.bookId, status: 1 })
                    if (res.code == 0&&res.data.list.length>0) {
                        text += "【元素】\n"
                        res.data.list.forEach(item => {
                            text += `${item.name}:${item.type},${item.content}`
                        })

                    }
                  
                    let resChapter = await http.getChapterlast({ bookId: this.bookId, limit: 10 })
                    let textChapter = ""
                    if (resChapter.code == 0&&resChapter.data.length>0&&resChapter.data[0].content!="") {
                        resChapter.data.reverse()
                        text += "\n【前面章节】\n"
                        resChapter.data.forEach(item => {
                            if (item.content) {
                                text += `第${item.index}章 ${item.name}:${item.content}`
                            }

                        })

                    }
                    // //上一章内容
                    // text+=textChapter
                    if (this.articleContent!="") {
                        text += "\n正在写作内容：" + this.articleContent
                    }

                    text += "\n用户要求扩写的内容：" + this.aiQuestion
                    this.previewContent = text
                },
                async toggleElementStatus(element) {
                    try {
                        const newStatus = element.status === 1 ? 0 : 1;
                        const res = await http.updateEle({
                            id: element.id,
                            status: newStatus,
                            bookId: this.bookId
                        });
                        if (res.code === 0) {
                            this.$message.success(`状态已修改为${newStatus === 1 ? '出场' : '离场'}`);
                            this.fetchElements();
                        }
                    } catch (error) {
                        console.error('修改状态失败:', error);
                        this.$message.error('修改状态失败');
                    }
                },
                async batchChangeStatus() {
                    if (this.selectedElements.length === 0) return;

                    for (let item of this.selectedElements) {
                        await http.updateEle({ id: item.id, status: !item.status, bookId: this.bookId });
                    }
                    this.fetchElements();
                },
                async fetchElements() {
                    try {
                        const res = await http.getEleList({
                            bookId: this.bookId,
                            page: this.elementPage,
                            pageSize: this.elementPageSize
                        });
                        if (res.code === 0) {
                            this.elements = res.data.list;
                            this.elementTotal = res.data.total;
                        }
                    } catch (error) {
                        console.error('获取元素列表失败:', error);
                    }
                },
                handleElementSelectionChange(val) {
                    this.selectedElements = val;
                },
                showAddElementDialog() {
                    this.currentElement = {
                        name: '',
                        type: '',
                        status: 1,
                        content: ''
                    };
                    this.elementDialogVisible = true;
                },
                editElement(element) {
                    this.currentElement = { ...element };
                    this.elementDialogVisible = true;
                },
                async saveElement() {
                    try {
                        let res=null;
                        if (this.currentElement.id) {
                            res = await http.updateEle({
                                ...this.currentElement,
                                bookId: this.bookId
                            });
                        }else{
                            res = await http.createEle({
                            ...this.currentElement,
                            bookId: this.bookId
                        });
                           
                        }
                       
                        if (res.code === 0) {
                            this.$message.success('保存成功');
                            this.elementDialogVisible = false;
                            this.fetchElements();
                        }
                    } catch (error) {
                        console.error('保存元素失败:', error);
                    }
                },
                async deleteSelectedElements() {
                    const ids = this.selectedElements.map(item => item.id);
                    for (const id of ids) {
                        await http.deleteEle(id);
                    }
                    this.fetchElements();


                },
                async updateBook() {
                    if (!this.bookId) return;

                    try {
                        const res = await http.updateBook({
                            id: this.bookId,
                            prompt: this.book.prompt,
                            settings: this.book.settings
                        });

                        if (res.code === 0) {
                            this.$message.success('书籍信息更新成功');
                        } else {
                            this.$message.error(res.message || '更新失败');
                        }
                    } catch (error) {
                        console.error('更新书籍失败:', error);
                        this.$message.error('更新书籍失败');
                    }
                },
                async fetchBook() {
                    if (!this.bookId) return;
                    const res = await http.getBook(this.bookId);
                    console.log(res);
                    if (res.code != 0) {
                        this.$message.error(res.message);
                        return;
                    }
                    this.book = res.data;
                },
                showSummaryDialog() {
                    this.summaryDialogVisible = true;
                },
                handleKeyDown(e) {
                    if (e.ctrlKey && e.key === 'Enter') {
                        this.submitAIQuestion();
                    }
                },
                scrollToBottom() {
                    this.$nextTick(() => {
                        const textarea = this.$refs.articleInput?.textarea;
                        if (textarea) {
                            textarea.scrollTop = textarea.scrollHeight;
                        }
                    });
                },
                async save() {
                    if (!this.selectedChapter) return;

                    let res = await http.updateChapter({ id: this.selectedChapter.id, content: this.articleContent, summary: this.summary });
                    if (res.code == 0) {
                        this.$message.success('章节保存成功');
                    } else {
                        this.$message.error(res.message);
                    }
                },
                async getChapter() {
                    if (!this.selectedChapter) return;
                    this.articleContent = '';
                    try {
                        const res = await http.getChapter(this.selectedChapter.id);
                        if (res.code != 0) {

                            this.$message.error(res.message);
                            return;
                        }
                        this.articleContent = res.data.content;
                        this.summary = res.data.summary;

                    } catch (error) {
                        this.$message.error('获取章节内容失败');
                        console.error(error);
                    }

                },
                async fetchChapters() {
                    if (!this.bookId) return;
                    this.chapters = []; // 清空章节列表，防止重复加载
                    try {
                        const res = await http.getChapterList({ bookId: this.bookId, page: this.currentPage, pageSize: this.pageSize });
                        if (res.code != 0) {
                            this.$message.error(res.message);
                            return;
                        } else {
                            if (!res.data.list) {
                                this.$message.warning('当前书籍暂无章节,请创建章节');
                                return;
                            }
                            this.chapters = res.data.list;
                            this.selectedChapter = this.chapters[0];
                            this.totalChapters = res.data.total;
                            this.getChapter();
                        }

                    } catch (error) {
                        this.$message.error('获取章节列表失败');
                        console.error(error);
                    }
                },

                selectChapter(chapter) {
                    this.selectedChapter = chapter;
                    this.getChapter();
                    // 这里可以加载章节内容
                },

                showCreateChapterDialog() {
                    this.createChapterDialogVisible = true;
                    this.newChapterName = '';
                },

                async createChapter() {
                    if (!this.newChapterName) {
                        this.$message.warning('请输入章节名称');
                        return;
                    }


                    let res = await http.createChapter({ index: this.newChapterIndex, name: this.newChapterName, bookId: this.bookId });
                    if (res.code == 0) {
                        this.$message.success('章节创建成功');
                    } else {
                        this.$message.error(res.message);
                    }

                    this.createChapterDialogVisible = false;
                    this.fetchChapters();

                },

                async deleteSelectedChapter() {
                    if (!this.selectedChapter) return;

                    await this.$confirm('确定要删除这个章节吗?', '提示', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    });
                    let res = await http.deleteChapter(this.selectedChapter.id);
                    console.log(res);
                    if (res.code == 0) {
                        this.$message.success('章节删除成功');
                        this.selectedChapter = null;
                        this.fetchChapters();
                    } else {
                        this.$message.error(res.msg);
                    }

                },

                handlePageChange(page) {
                    this.currentPage = page;
                    this.fetchChapters();
                },
                toggleAIChat() {
                    this.showAIChat = !this.showAIChat;
                },
                stopAI() {
                    this.stopAIRequest = true;
                    this.aiLoading = false;
                    this.$message.info('已停止AI生成');
                },
               
            }
        }).use(ElementPlus).mount('#app');
        
        // 页面加载时读取缓存的提问内容
        const lastQuestion = localStorage.getItem('lastQuestion');
        if (lastQuestion) {
            app.previewContent = lastQuestion;
        }
    </script>
</body>

</html>